use std::cmp;
use std::ffi::CString;
use std::collections::VecDeque;
-use crate::conf::conf_get;
+use crate::conf::{conf_get, get_memval};
+
+pub static mut DCERPC_MAX_STUB_SIZE: u32 = 1048576;
// Constant DCERPC UDP Header length
pub const DCERPC_HDR_LEN: u16 = 16;
_ => DCERPC_TYPE_UNKNOWN,
}
}
+#[inline(always)]
+pub fn cfg_max_stub_size() -> u32 {
+ unsafe { DCERPC_MAX_STUB_SIZE }
+}
+
#[derive(Default, Debug)]
pub struct DCERPCTransaction {
}
let input_slice = &input[..stub_len as usize];
- stub_data_buffer.extend_from_slice(input_slice);
+ let max_size = cfg_max_stub_size() as usize;
+ if (stub_data_buffer.len() + input_slice.len()) < max_size {
+ stub_data_buffer.extend_from_slice(input_slice);
+ } else if stub_data_buffer.len() < max_size {
+ stub_data_buffer.extend_from_slice(&input_slice[..max_size - stub_data_buffer.len()]);
+ }
stub_len
}
}
}
SCLogDebug!("Rust DCERPC parser registered.");
+ let retval = conf_get("app-layer.protocols.dcerpc.max-stub-size");
+ if let Some(val) = retval {
+ match get_memval(val) {
+ Ok(retval) => {
+ if retval > 0 {
+ DCERPC_MAX_STUB_SIZE = retval as u32;
+ } else {
+ SCLogError!("Invalid max-stub-size value");
+ }
+ }
+ Err(_) => {
+ SCLogError!("Invalid max-stub-size value");
+ }
+ }
+ }
} else {
SCLogDebug!("Protocol detector and parser disabled for DCERPC.");
}
-/* Copyright (C) 2020 Open Information Security Foundation
+/* Copyright (C) 2020-2026 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
use crate::core::{self, Direction, DIR_BOTH};
use crate::dcerpc::dcerpc::{
DCERPCTransaction, DCERPC_MAX_TX, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG,
- rs_dcerpc_get_alstate_progress, ALPROTO_DCERPC, PARSER_NAME,
+ rs_dcerpc_get_alstate_progress, ALPROTO_DCERPC, PARSER_NAME, cfg_max_stub_size,
};
use nom7::Err;
use std;
tx.tx_data.updated_ts = true;
let done = (hdr.flags1 & PFCL1_FRAG) == 0 || (hdr.flags1 & PFCL1_LASTFRAG) != 0;
+ let max_size = cfg_max_stub_size() as usize;
match hdr.pkt_type {
DCERPC_TYPE_REQUEST => {
- tx.stub_data_buffer_ts.extend_from_slice(input);
tx.frag_cnt_ts += 1;
+ if input.len() + tx.stub_data_buffer_ts.len() < max_size {
+ tx.stub_data_buffer_ts.extend_from_slice(input);
+ } else if tx.stub_data_buffer_ts.len() < max_size {
+ tx.stub_data_buffer_ts.extend_from_slice(&input[..max_size - tx.stub_data_buffer_ts.len()]);
+ }
if done {
tx.req_done = true;
}
return true;
}
DCERPC_TYPE_RESPONSE => {
- tx.stub_data_buffer_tc.extend_from_slice(input);
tx.frag_cnt_tc += 1;
+ if input.len() + tx.stub_data_buffer_tc.len() < max_size {
+ tx.stub_data_buffer_tc.extend_from_slice(input);
+ } else if tx.stub_data_buffer_tc.len() < max_size {
+ tx.stub_data_buffer_tc.extend_from_slice(&input[..max_size - tx.stub_data_buffer_tc.len()]);
+ }
if done {
tx.resp_done = true;
}
}
}
-
#[cfg(test)]
mod tests {
use crate::applayer::AppLayerResult;
// written by Victor Julien
use uuid;
-use crate::smb::smb::*;
+use crate::smb::smb::{cfg_max_stub_size, *};
use crate::smb::smb2::*;
use crate::smb::dcerpc_records::*;
use crate::smb::events::*;
SCLogDebug!("previous CMD {} found at tx {} => {:?}",
dcer.packet_type, tx.id, tx);
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
- SCLogDebug!("additional frag of size {}", recr.data.len());
- tdn.stub_data_ts.extend_from_slice(recr.data);
tdn.frag_cnt_ts += 1;
- SCLogDebug!("stub_data now {}", tdn.stub_data_ts.len());
+ let max_size = cfg_max_stub_size() as usize;
+ if recr.data.len() + tdn.stub_data_ts.len() < max_size {
+ SCLogDebug!("additional frag of size {}", recr.data.len());
+ tdn.stub_data_ts.extend_from_slice(recr.data);
+ SCLogDebug!("stub_data now {}", tdn.stub_data_ts.len());
+ } else if tdn.stub_data_ts.len() < max_size {
+ tdn.stub_data_ts.extend_from_slice(&recr.data[..max_size - tdn.stub_data_ts.len()]);
+ }
}
if dcer.last_frag {
SCLogDebug!("last frag set, so request side of DCERPC closed");
SCLogDebug!("DCERPC: REQUEST {:?}", recr);
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
SCLogDebug!("first frag size {}", recr.data.len());
- tdn.stub_data_ts.extend_from_slice(recr.data);
tdn.opnum = recr.opnum;
tdn.context_id = recr.context_id;
tdn.frag_cnt_ts += 1;
- SCLogDebug!("DCERPC: REQUEST opnum {} stub data len {}",
- tdn.opnum, tdn.stub_data_ts.len());
+ let max_size = cfg_max_stub_size() as usize;
+ if tdn.stub_data_ts.len() + recr.data.len() < max_size {
+ tdn.stub_data_ts.extend_from_slice(recr.data);
+ SCLogDebug!("DCERPC: REQUEST opnum {} stub data len {}",
+ tdn.opnum, tdn.stub_data_ts.len());
+ } else if tdn.stub_data_ts.len() < max_size {
+ tdn.stub_data_ts.extend_from_slice(&recr.data[..max_size - tdn.stub_data_ts.len()]);
+ }
}
if dcer.last_frag {
tx.request_done = true;
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
SCLogDebug!("CMD 11 found at tx {}", tx.id);
tdn.set_result(DCERPC_TYPE_RESPONSE);
- tdn.stub_data_tc.extend_from_slice(respr.data);
+ let max_size = cfg_max_stub_size() as usize;
tdn.frag_cnt_tc += 1;
+ if tdn.stub_data_tc.len() + respr.data.len() < max_size {
+ tdn.stub_data_tc.extend_from_slice(respr.data);
+ } else if tdn.stub_data_tc.len() < max_size {
+ tdn.stub_data_tc.extend_from_slice(&respr.data[..max_size - tdn.stub_data_tc.len()]);
+ }
}
tx.vercmd.set_ntstatus(ntstatus);
tx.response_done = dcer.last_frag;
pub static mut SMB_CFG_MAX_WRITE_QUEUE_SIZE: u32 = 67108864;
pub static mut SMB_CFG_MAX_WRITE_QUEUE_CNT: u32 = 64;
+pub static mut SMB_DCERPC_MAX_STUB_SIZE: u32 = 1048576;
+
static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN;
static mut SMB_MAX_TX: usize = 1024;
SCLogError!("Invalid value for smb.max-tx");
}
}
+ let retval = conf_get("app-layer.protocols.smb.dcerpc.max-stub-size");
+ if let Some(val) = retval {
+ match get_memval(val) {
+ Ok(retval) => {
+ if retval > 0 {
+ SMB_DCERPC_MAX_STUB_SIZE = retval as u32;
+ } else {
+ SCLogError!("Invalid max-stub-size value");
+ }
+ }
+ Err(_) => {
+ SCLogError!("Invalid max-stub-size value");
+ }
+ }
+ }
SCLogConfig!("read: max record size: {}, max queued chunks {}, max queued size {}",
SMB_CFG_MAX_READ_SIZE, SMB_CFG_MAX_READ_QUEUE_CNT, SMB_CFG_MAX_READ_QUEUE_SIZE);
SCLogConfig!("write: max record size: {}, max queued chunks {}, max queued size {}",
SCLogDebug!("Protocol detector and parser disabled for SMB.");
}
}
+
+#[inline(always)]
+pub fn cfg_max_stub_size() -> u32 {
+ unsafe { SMB_DCERPC_MAX_STUB_SIZE }
+}
+
enabled: yes
# Maximum number of live DCERPC transactions per flow
# max-tx: 1024
+ #max-stub-size: 1MiB
+
ftp:
enabled: yes
# memcap: 64mb
# Stream reassembly size for SMB streams. By default track it completely.
#stream-depth: 0
+ #dcerpc:
+ # max-stub-size: 1MiB
nfs:
enabled: yes